package com.mxpio.erp.inventory.policy.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mxpio.erp.common.inventory.entity.WarehouseOrderLine;
import org.apache.commons.collections4.CollectionUtils;

import com.mxpio.erp.common.enums.OrderEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.inventory.entity.InvFlow;
import com.mxpio.erp.common.inventory.entity.WarehouseOrder;
import com.mxpio.erp.common.jpa.model.Order;
import com.mxpio.erp.common.order.policy.OrderContext;
import com.mxpio.erp.common.vo.OrderExcuteLineVo;
import com.mxpio.erp.inventory.policy.AbstractWoPolicy;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.security.util.SecurityUtils;

public class DefaultWoPolicy extends AbstractWoPolicy {
	
	private List<OrderExcuteLineVo> orderExcuteVos;
	
	public DefaultWoPolicy(List<OrderExcuteLineVo> orderExcuteVos) {
		this.orderExcuteVos = orderExcuteVos;
	}
	
	@Override
	public void execute(OrderContext context) {
		Order order = context.getEntity();
		if(order instanceof WarehouseOrder) {
			List<OrderExcuteLineVo> orderExcuteVos = context.getOrderExcuteVos();
			List<InvFlow> invFlows = new ArrayList<>();
			
			Map<String, BigDecimal> sumQuantity = new HashMap<String, BigDecimal>();
			for(OrderExcuteLineVo vo : orderExcuteVos) {
				InvFlow invFlow = new InvFlow();
				String accessType = ((WarehouseOrder) order).getAccessType();
				invFlow.setAccessType(accessType);
				invFlow.setItemCode(vo.getItemCode());
				invFlow.setWhCode(((WarehouseOrder) order).getWhCode());
				// 批次控制
				if(OrderEnums.AccessType.IN.getCode().equals(accessType)) {
					if(vo.getLotNo() == null) {
						invFlow.setLotNo(context.getLotService().getNewLot(order, vo));
					}else {
						invFlow.setLotNo(vo.getLotNo());
					}
				}else {
					if(vo.getLotNo() == null) {
						context.addError("未分配批次");
						break;
					}else {
						invFlow.setLotNo(vo.getLotNo());
					}
				}
				invFlow.setQuantity(vo.getQuantity());
				// 库存数量控制
				if(OrderEnums.AccessType.OUT.getCode().equals(accessType)) {
					BigDecimal stock = context.getLotService().getStock(invFlow.getWhCode(), invFlow.getItemCode(), invFlow.getLotNo());
					if(stock.compareTo(invFlow.getQuantity()) < 0) {
						context.addError("物料：" + invFlow.getItemCode() + "库存不足");
						break;
					}
				}
				
				// 单据数量控制
				BigDecimal completeQuantity = context.getLotService().getMaxQuantityByWo(vo.getBizWoNo(), vo.getBizWoLineNo());
				BigDecimal currentQuan = sumQuantity.get(vo.getBizWoNo() + "#" + vo.getBizWoLineNo());
				if(currentQuan == null) {
					BigDecimal maxQuantity = vo.getLineQuantity()==null?BigDecimal.ZERO:vo.getLineQuantity();
					currentQuan = maxQuantity.subtract(completeQuantity).subtract(vo.getQuantity());
				}else {
					currentQuan = currentQuan.subtract(vo.getQuantity());
				}
				if(currentQuan.compareTo(BigDecimal.ZERO) < 0) {
					context.addError("物料：" + invFlow.getItemCode() + "超过最大执行数量");
					break;
				}
				
				invFlow.setMemo(((WarehouseOrder) order).getMemo());
				invFlow.setOriginBizNo(((WarehouseOrder) order).getOriginBizNo());
				invFlow.setOriginBizType(((WarehouseOrder) order).getOriginBizType());
				invFlow.setOriginBizLineNo(vo.getBizOrderlineNo());
				invFlow.setWoBizNo(((WarehouseOrder) order).getBizNo());
				invFlow.setWoBizType(((WarehouseOrder) order).getWoType());
				invFlow.setWoBizLineNo(vo.getBizWoLineNo());
				invFlows.add(invFlow);
			}
			if(CollectionUtils.isEmpty(context.getErrors())) {
				JpaUtil.save(invFlows);
			}
		}else {
			context.addError("单据类型错误");
		}
	}
	
	@Override
	public OrderContext config(OrderContext context) {
		context.setOrderExcuteVos(orderExcuteVos);
		return context;
	}

	@Override
	public boolean beforeExecute(OrderContext context) {
		return true;
	}

	@Override
	public void afterExecute(OrderContext context) {
		if(CollectionUtils.isEmpty(context.getErrors())){
			Order wo = context.getEntity();
			if (judgeWOCompletion(context)){
				wo.setOrderStatus(OrderStatusEnums.OrderStatus.FINISHED.getStatusCode());
				wo.setExecuteTime(new Date());
				wo.setExecutor(SecurityUtils.getLoginUsername());
				JpaUtil.update(wo);
			}else{
				if(OrderStatusEnums.OrderStatus.ORDERED.getStatusCode().equals(wo.getOrderStatus())||
						OrderStatusEnums.OrderStatus.PLAN.getStatusCode().equals(wo.getOrderStatus())) {
					wo.setOrderStatus(OrderStatusEnums.OrderStatus.PROCESSING.getStatusCode());
					wo.setExecuteTime(new Date());
					wo.setExecutor(SecurityUtils.getLoginUsername());
					JpaUtil.update(wo);
				}
			}
		}
	}

	private boolean judgeWOCompletion(OrderContext context){//判断仓单是否已执行完毕
		Order order = context.getEntity();
		List<WarehouseOrderLine> lines = JpaUtil.linq(WarehouseOrderLine.class).equal("bizNo", order.getBizNo()).list();
		if (lines.size()>0){
			for (WarehouseOrderLine line:lines){
				BigDecimal completeQuantity = context.getLotService().getMaxQuantityByWo(line.getBizNo(), line.getLineNo());
				if (line.getQuantity().compareTo(completeQuantity)!=0){
					return false;
				}
			}
		}else{
			return false;
		}
		return true;
	}
}
